package com.treasure.mall.biz.service.core.integral.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.integral.IntegralOrderCondition;
import com.treasure.mall.biz.dto.integral.IntegralOrderCreateDTO;
import com.treasure.mall.biz.dto.user.ModifyIntegralDTO;
import com.treasure.mall.biz.entity.integral.IntegralOrderPO;
import com.treasure.mall.biz.entity.integral.IntegralOrderPO_;
import com.treasure.mall.biz.entity.integral.IntegralProductPO;
import com.treasure.mall.biz.entity.integral.IntegralProductPO_;
import com.treasure.mall.biz.remote.wx.WxTemplateMessageService;
import com.treasure.mall.biz.remote.wx.dto.DeliverTemplateDTO;
import com.treasure.mall.biz.repository.integral.IntegralOrderRepository;
import com.treasure.mall.biz.service.core.integral.IntegralOrderService;
import com.treasure.mall.biz.service.core.integral.IntegralProductService;
import com.treasure.mall.biz.service.core.user.UserService;
import com.treasure.mall.zbq.common.RandomUtils;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.base.ResultCodeEnum;
import com.treasure.mall.zbq.common.exception.ApiException;
import com.treasure.mall.zbq.common.ienum.integral.IntegralEnums;
import com.treasure.mall.zbq.common.ienum.order.OrderEnums;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/8/22
 */
@Service
public class IntegralOrderServiceImpl extends AbstractSearchableCrudService<IntegralOrderPO, String> implements IntegralOrderService {
    @Resource
    private UserService userService;
    @Resource
    private IntegralProductService integralProductService;
    @Resource
    private WxTemplateMessageService messageService;
    private IntegralOrderRepository integralOrderRepository;

    @Autowired
    protected IntegralOrderServiceImpl(IntegralOrderRepository repository) {
        super(repository);
        this.integralOrderRepository = repository;
    }

    @Override
    protected SpecificationAndSort<IntegralOrderPO> specificationAndSort(BaseSearchDTO searchDTO) {
        IntegralOrderCondition condition = (IntegralOrderCondition) searchDTO;

        Specification<IntegralOrderPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            predicates.add(cb.equal(root.get(IntegralProductPO_.deleted), false));

            if (!StringUtils.isEmpty(condition.getId())) {
                predicates.add(cb.equal(root.get(IntegralOrderPO_.id), likeAll(condition.getId())));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public IntegralOrderPO save(BaseSaveDTO saveDTO) {
        return null;
    }

    @Override
    @Transactional
    public IntegralOrderPO create(IntegralOrderCreateDTO createDTO) {
        IntegralProductPO productPO = integralProductService.findById(createDTO.getProductId());
        //判断库存
        if (productPO.getStore() < createDTO.getNum()) {
            throw new ApiException(ApiResult.error("当前商品库存不足"));
        }
        //判断限购
        if (productPO.getLimitExchange() > 0) {
            int userBuyCount = integralOrderRepository.userBuyCount(createDTO.getUserPO().getUserId());
            if (userBuyCount + createDTO.getNum() > productPO.getLimitExchange()) {
                throw new ApiException(ApiResult.error("兑换超过限购数量"));
            }
        }

        IntegralOrderPO orderPO = new IntegralOrderPO();
        orderPO.setId(RandomUtils.randomFlowNo());
        orderPO.setUserPO(createDTO.getUserPO());
        orderPO.setProduct(new IntegralOrderPO.Product(productPO));
        orderPO.setNum(createDTO.getNum());
        orderPO.setTotalIntegral(productPO.getIntegral());
        orderPO.setPmtIntegral(0);
        orderPO.setFinalIntegral(orderPO.getTotalIntegral() - orderPO.getPmtIntegral());
        orderPO.setReceivingInfo(createDTO.getReceivingInfo());
        orderPO.setDeliverStatus(OrderEnums.DeliverStatus.TO_DELIVER);

        if (createDTO.getUserPO().getIntegral() < orderPO.getFinalIntegral()) {
            throw new ApiException(ApiResult.error(ResultCodeEnum.INTEGRAL_FAILED));
        }

        orderPO = save(orderPO);

        //扣减库存
        integralProductService.minusStore(productPO.getId(), orderPO.getNum());

        //扣积分
        userService.modifyIntegral(
                ModifyIntegralDTO.builder()
                        .userId(createDTO.getUserPO().getUserId())
                        .integral(orderPO.getFinalIntegral() * -1)
                        .orderId(orderPO.getId())
                        .logType(IntegralEnums.LogType.EXCHANGE)
                        .build()
        );

        return orderPO;
    }

    @Override
    public void deliver(String orderId, String expressNo, String expressCompany) {
        IntegralOrderPO po = findById(orderId);
        po.setExpressNo(expressNo);
        po.setExpressCompany(expressCompany);

        save(po);

        //小程序推送
        messageService.deliverSuccessMessage(
                DeliverTemplateDTO
                        .builder()
                        .userId(po.getUserPO().getUserId())
                        .receivingInfo(po.getReceivingInfo())
                        .expressCom(expressCompany)
                        .expressNo(expressNo)
                        .build()
        );
    }
}
